package de.fhaugsburg.games.boardgames.scrabble.gui;

import java.awt.Component;
import java.awt.Point;
import java.awt.event.MouseEvent;

import javax.swing.JLayeredPane;
import javax.swing.SwingUtilities;

import de.fhaugsburg.games.boardgames.ModelChangedListener;
import de.fhaugsburg.games.boardgames.Player.PlayerType;
import de.fhaugsburg.games.boardgames.exceptions.GameException;
import de.fhaugsburg.games.boardgames.exceptions.IllegalMoveException;
import de.fhaugsburg.games.boardgames.scrabble.IScrabbleEngine;
import de.fhaugsburg.games.boardgames.scrabble.ModelChangedEvent;
import de.fhaugsburg.games.boardgames.scrabble.gui.GLetterPiece.GLetterState;
import de.fhaugsburg.games.boardgames.scrabble.scrabbleboard.LetterPiece;

public class Controller implements ModelChangedListener {

	private IScrabbleEngine engine; 
	private ScrabbleMainWindow gui;
	private Point dragPoint;
	private GLetterPiece dragLetter, dragLetterOriginal;
	
	
	public Controller(IScrabbleEngine engine, ScrabbleMainWindow window) {
		this.engine = engine;
		this.gui = window;
	}
	
	

	/**
	 * news from the engine
	 */
	public void modelChanged(ModelChangedEvent ev) {
//		System.out.println("model changed");
//		System.out.println("changed");
//		gui.boardView.updateBoardView();
		gui.reDraw();		
//		gui.pack();
	}


	
	
	
	/**
	 * Dialog to start a new game
	 */
	public void newGameDialog(){
		NewgameDialog newgameDialog = new NewgameDialog(this);
	}
	
	
	/**
	 * add players before starting game
	 * @param playerName
	 * @param playerType
	 */
	public void addPlayer(String playerName, PlayerType playerType){
		try {
			engine.addPlayer(playerName, playerType);
		} catch (GameException e) {
			errorMessage("Error", e.getMessage());
		}
	}

	
	/**
	 * starts a new game
	 */
	public void newGame() {
		engine.newGame();
		/**
		 * just for testing, doesn't work as expected, engine has to be a Thread
		 */
		Runnable newGameRun = new Runnable() {
			public void run() {
		    	 try {
					engine.startGame();
				} catch (GameException e) {
					errorMessage("Error", e.getMessage());
					e.printStackTrace();
				}
//		         System.out.println("newgame " + Thread.currentThread());
		     }
		 };

		 SwingUtilities.invokeLater(newGameRun);
		//engine.newGame();
		/*try {
			engine.startGame();
		} catch (GameException e) {
			errorMessage("Error", e.getMessage());
		}*/
	}
	
	
	/**
	 * display errormessage from GUI
	 * @param title
	 * @param message
	 */
	public void errorMessage(String title, String message){
		gui.errorMessage(title, message);
	}
	
	
	
	
	public void startDragPiece(MouseEvent e, GLetterPiece piece){
		
		if (piece.getLetterState() != GLetterState.FIXED){
//			if (piece.getLetterState() == GLetterState.BAR){
				
//			}
			this.dragPoint = e.getPoint();
			int pieceX = (int) piece.getSize().width;
			int pieceY = (int) piece.getSize().height;
			int drX = (int) e.getPoint().getX();
			int drY = (int) e.getPoint().getY();
			
			dragLetter = new GLetterPiece(piece.getLetterPiece(), GLetterState.DRAGGING);
			dragLetter.setLocation(drX - pieceX, drY - pieceY);
			dragLetter.setLetterOrigin(piece.getLetterState());
			
			gui.getLayeredPane().add(dragLetter, JLayeredPane.DRAG_LAYER);
			piece.getParent().remove(piece);		//remove parent
			repaint();
		}
	}
	
	
	
	
	public void dragPiece(Point point){
		if (dragLetter != null){
			int pieceX = (int) dragLetter.getSize().width;
			int pieceY = (int) dragLetter.getSize().height;
			int locX = (int) (point.getX()) - pieceX;// - dragPoint.getX());
			int locY = (int) (point.getY()) - pieceY;// - dragPoint.getY());
//			System.out.println("dragging..." + locX + ","+ locY);
			dragLetter.setLocation(locX, locY);
//			gui.getLayeredPane().setLayer(dragLetter, JLayeredPane.DRAG_LAYER);
//			gui.repaint();
		}
	}
	
	
	
	
	public void dropPiece(MouseEvent e){
		if (dragLetter != null){
			Component comp = gui.findComponentAt(e.getPoint());
			if (comp instanceof GSquare){
				//new letter to add from players bar
				if (dragLetter.getLetterOrigin() == GLetterState.BAR){
					GSquare square = (GSquare) comp;
					int row = square.getRow();
					int column = square.getColumn();
					LetterPiece letter = dragLetter.getLetterPiece();
					try {
						engine.setLetter(letter, row, column);
						endDrag();
					} catch (IllegalMoveException e1) {
						endDrag();
						errorMessage("Illegal move", e1.getMessage());
					}
				}
			}else{
				//other locations, lettersack...
				endDrag();
			}
		}
	}
	
	

	
	/**
	 * ends a drap an drop operation
	 */
	public void endDrag(){
		dragLetter.getParent().remove(dragLetter);
		dragLetter = null;
		repaint();
	}
	
	
	
	
	/**
	 * repaints
	 */
	public void repaint(){
		modelChanged(new ModelChangedEvent(this));
	}
	
	
	
	public ScrabbleMainWindow getGUI(){
		return gui;
	}
}